﻿#include "logger/PatternFormatter.h"

#include <cctype>  // for std::isdigit
#include <iomanip>
#include <map>
#include <sstream>
#include <vector>

#include "logger/LogMessageInfo.h"  // 假设 LogMessageInfo 和 LogLevel 在这里定义

namespace Logging {
// ★★★ 1. 定义新的数据结构来描述一个格式化指令 ★★★
// 这个结构体将持有格式化标志符的所有信息
struct FormatSpecifier {
  char flag = '\0';         // 标志符, e.g., 'l', 'v', 'Y'
  int min_width = 0;        // 最小宽度, e.g., 8 in "%-8l"
  bool align_left = false;  // 是否左对齐, e.g., true for "%-8l"
};

// 这个结构体代表解析后的一个“块”，可以是一个字面量，也可以是一个格式化指令
struct PatternChunk {
  bool is_literal;
  std::string literal_text;  // 当 is_literal 为 true 时使用
  FormatSpecifier spec;      // 当 is_literal 为 false 时使用
};

// 将所有解析和格式化的逻辑都放在 Impl 类中
class PatternFormatter::Impl {
 public:
  std::string pattern_;
  std::vector<PatternChunk> chunks_;  // ★★★ 使用新的数据结构 ★★★

  explicit Impl(std::string pattern) : pattern_(std::move(pattern)) {
    parse_pattern();
  }

  // ★★★ 2. 重写解析器以支持宽度和对齐 ★★★
  void parse_pattern() {
    chunks_.clear();
    std::string current_literal;
    size_t i = 0;
    while (i < pattern_.length()) {
      if (pattern_[i] == '%') {
        // 先将之前累积的字面量存起来
        if (!current_literal.empty()) {
          chunks_.push_back({true, current_literal, {}});
          current_literal.clear();
        }

        i++;                           // 移动到 '%' 之后
        if (i >= pattern_.length()) {  // 模式以'%'结尾
          current_literal += '%';
          break;
        }

        if (pattern_[i] == '%') {  // 处理 "%%"
          current_literal += '%';
          i++;
          continue;
        }

        // --- 开始解析格式化指令 ---
        FormatSpecifier spec;

        // a. 解析对齐标志 '-'
        if (pattern_[i] == '-') {
          spec.align_left = true;
          i++;
        }

        // b. 解析宽度 (数字)
        std::string width_str;
        while (i < pattern_.length() && std::isdigit(pattern_[i])) {
          width_str += pattern_[i];
          i++;
        }
        if (!width_str.empty()) {
          spec.min_width = std::stoi(width_str);
        }

        // c. 解析标志符
        if (i < pattern_.length()) {
          spec.flag = pattern_[i];
          i++;
          chunks_.push_back({false, "", spec});
        } else {  // 模式以 "%-8" 这样的不完整指令结尾
          // 将其视为字面量
          current_literal +=
              '%' + (spec.align_left ? std::string("-") : "") + width_str;
        }
      } else {
        current_literal += pattern_[i];
        i++;
      }
    }

    // 将最后的字面量存起来
    if (!current_literal.empty()) {
      chunks_.push_back({true, current_literal, {}});
    }
  }

  const char *level_to_string(LogLevel level) {
    switch (level) {
        // 假设您的 LogLevel 枚举如下定义
      case LogLevel::kTrace:
        return "TRACE";
      case LogLevel::kDebug:
        return "DEBUG";
      case LogLevel::kInfo:
        return "INFO";
      case LogLevel::kWarn:
        return "WARN";
      case LogLevel::kError:
        return "ERROR";
      case LogLevel::kCritical:
        return "CRITICAL";
      default:
        return "UNKNOWN";
    }
  }

  // ★★★ 3. 重写格式化器以应用宽度和对齐 ★★★
  std::string format(const LogMessageInfo &message) {
    std::ostringstream oss;
    auto tt = std::chrono::system_clock::to_time_t(message.timestamp);
    std::tm t;
#ifdef _WIN32
    localtime_s(&t, &tt);
#else
    localtime_r(&tt, &t);  // POSIX systems
#endif

    for (const auto &chunk : chunks_) {
      if (chunk.is_literal) {
        oss << chunk.literal_text;
      } else {
        // --- 先生成内容 ---
        std::ostringstream content_oss;
        switch (chunk.spec.flag) {
          case 'Y':
            content_oss << std::put_time(&t, "%Y");
            break;
          case 'm':
            content_oss << std::put_time(&t, "%m");
            break;
          case 'd':
            content_oss << std::put_time(&t, "%d");
            break;
          case 'H':
            content_oss << std::put_time(&t, "%H");
            break;
          case 'M':
            content_oss << std::put_time(&t, "%M");
            break;
          case 'S':
            content_oss << std::put_time(&t, "%S");
            break;
          case 'e': {  // Milliseconds
            auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
                          message.timestamp.time_since_epoch()) %
                      1000;
            content_oss << std::setfill('0') << std::setw(3) << ms.count();
            break;
          }
          case 'f': {  // Microseconds
            auto us = std::chrono::duration_cast<std::chrono::microseconds>(
                          message.timestamp.time_since_epoch()) %
                      1000000;
            content_oss << std::setfill('0') << std::setw(6) << us.count();
            break;
          }
          case 'l':  // Log level
          case 'p':
            content_oss << level_to_string(message.level);
            break;
          case 't':
            content_oss << message.thread_id;
            break;
          case 'n':  // Category name
          case 'c':
            content_oss << message.category;
            break;
          case 'v':
            content_oss << message.message;
            break;
          default:  // 未知标志，原样输出
            content_oss << '%' << chunk.spec.flag;
            break;
        }
        std::string content = content_oss.str();

        // --- 再应用格式化（宽度和对齐）---
        int padding = chunk.spec.min_width - static_cast<int>(content.length());
        if (padding > 0) {
          if (chunk.spec.align_left) {
            oss << content << std::string(padding, ' ');
          } else {
            oss << std::string(padding, ' ') << content;
          }
        } else {
          oss << content;
        }
      }
    }
    return oss.str();
  }
};

// PatternFormatter 的公共接口只是简单地委托给 PImpl
PatternFormatter::PatternFormatter(std::string pattern)
    : pimpl_(std::make_unique<Impl>(std::move(pattern))) {}

PatternFormatter::~PatternFormatter() = default;

std::string PatternFormatter::format(const LogMessageInfo &message) {
  return pimpl_->format(message);
}
}  // namespace Logging